package com.mainbo.youkev2;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.whty.apigateway.security.login.EncryptUtils;
import com.whty.apigateway.security.login.MD5Util;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Properties;

/**
 * Created by dell on 2016/12/5.
 */
@WebServlet(urlPatterns = "/youke/login")
public class Servlet extends HttpServlet {
    private static final Log log = LogFactory.getLog(Servlet.class);
    private Token token;
    private static String APPID = null;
    private static String APPSECRET = null;
    private static String GET_TOKEN_URL = null;
    private static String LOGIN_URL = null;

    //HttpClient连接池
    private final static PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
    //存放配置文件
    public final static Properties p = new Properties();

    /*代码块加载配置文件*/
    {
        InputStream in = null;
        try {
            in = Servlet.class.getClassLoader().getResourceAsStream("config.properties");
        } catch (Exception e) {
            log.error("加载配置文件失败",e);
        }
        try {
            //从流中读取到Properties中
            p.load(in);
            APPID = p.getProperty("APPID");
            APPSECRET = p.getProperty("APPSECRET");
            GET_TOKEN_URL = p.getProperty("GET_TOKEN_URL");
            LOGIN_URL = p.getProperty("LOGIN_URL");
            //关闭读取流
            if(in != null){
                in.close();
            }
        } catch (IOException e) {
            log.error("记载配置文件到Properties失败", e);
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        response.setCharacterEncoding("UTF-8");
        if(username == null || "".equals(username) || password == null || "".equals(password)){
            String errInfo = "{\"result\":\"301003\",\"desc\":\"username or password is null !\"}";
            log.info(errInfo);
            response.getWriter().print(errInfo);
        }else{
            log.info("username --> "+username);
            log.info("password --> "+password);
            synchronized (this){
                //获得token
                this.getToken();
                //登录
                response.getWriter().print(this.login(username, password));
            }
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        this.doPost(request, response);
    }

    //获得Token
    private Token getToken() {
        //获得当前时间
        long timeMillis = System.currentTimeMillis();
        //Token为Null或者Token过期，重新获取Token
        if (this.token == null || timeMillis > token.getValidtime()) {
            //生成keyinfo
            String paramValues = APPID + APPSECRET + timeMillis;
            byte[] hmacSHA = EncryptionUtils.getHmacSHA1(paramValues, APPSECRET);
            String keyinfo = EncryptionUtils.bytesToHexString(hmacSHA);
            keyinfo = keyinfo.toUpperCase();
            //参数设置
            JSONObject json = new JSONObject();
            json.put("appid", APPID);
            json.put("timestamp", timeMillis + "");
            json.put("keyinfo", keyinfo);
            //执行请求并返回响应体内容
            String responseBodyString = excutePostAndGetResponseBodyString(GET_TOKEN_URL, json);
            String tokenInfo = JSON.parseObject(responseBodyString).get("tokenInfo").toString();
            //封装Token
            token = JSON.parseObject(tokenInfo, Token.class);
            //对方提供的token有效期有问题，手动设置为10分钟
            token.setValidtime(System.currentTimeMillis()+10*60*1000);

        }
        return this.token;
    }

    //登录并返回账户信息
    private String login(String username, String password) {
        //处理密码
        password = disposePassword(password);
        //封装参数
        JSONObject json = new JSONObject();
        json.put("account", username);
        json.put("password", password);
        json.put("portaltype", 0);

        //执行请求并返回响应体内容
        String responseBodyString = this.excutePostAndGetResponseBodyString(LOGIN_URL + "?token=" + token.getToken(), json);

        log.info("登录结果 --> "+responseBodyString);

        return responseBodyString;
    }

    //执行http Post请求，返回响应体内容
    public String excutePostAndGetResponseBodyString(String url, JSONObject json) {
        String responseString = null;
        //获得HttpClient
        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();
        HttpPost httpPost = new HttpPost(url);
        try {
            //设置Post请求体
            httpPost.setEntity(new StringEntity(json.toJSONString(), "UTF-8"));
        } catch (UnsupportedEncodingException e) {

        }

        //执行HTTP请求
        try {
            HttpResponse response = httpClient.execute(httpPost);
            //获得response响应体数据流
            InputStream inputStream = response.getEntity().getContent();
            //获得ResponseBody字符串格式
            responseString = IOUtils.toString(inputStream, "UTF-8");
            log.info("http请求路径 --> "+url);
            log.info("http请求结果 --> "+responseString);
        } catch (Exception e) {
            log.error("执行Http请求失败",e);
        }
        return responseString;
    }

    //密码处理
    public String disposePassword(String password) {
        EncryptUtils eu = EncryptUtils.getInstance();
        return eu.encode(MD5Util.toMD5(password),"user_sercretkey");
    }

}
